package com.fjh.listener;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fjh.constant.QueueConstant;
import com.fjh.domain.Order;
import com.fjh.domain.OrderItem;
import com.fjh.feign.OrderProductFeign;
import com.fjh.model.EsChange;
import com.fjh.model.SkuChange;
import com.fjh.model.StockChange;
import com.fjh.service.OrderItemService;
import com.fjh.service.OrderService;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Component
@Slf4j
public class OrderListener {

    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderItemService orderItemService;

    @Autowired
    private OrderProductFeign orderProductFeign;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 监听订单取消或者超时未支付的情况
     * 取消订单或者说订单超时未支付  或者订单已完成
     * 拿到订单号
     * 查询订单表 status   如果这个状态不是1 或者 6 说明支付成功 我们直接签收消息 return
     * 如果这个状态是未支付等
     * 0.查询第三方支付平台 看到底有没有支付
     * 1.把订单表状态改为失败
     * 2.回滚mysql的库存
     * 3.回滚es的库存
     *
     * @param message
     * @param channel
     */
    @RabbitListener(queues = QueueConstant.ORDER_DEAD_QUEUE, concurrency = "3-5")
    public void handleOrderCancel(Message message, Channel channel) {
        String orderNum = new String(message.getBody());
        log.error("订单号为:" + orderNum);
        // 查询order表
        Order order = orderService.getOne(new LambdaQueryWrapper<Order>()
                .eq(Order::getOrderNumber, orderNum)
        );
        if (ObjectUtils.isEmpty(order)) {
            log.error("该订单号{}不存在", orderNum);
            try {
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return;
        }
        // 判断状态
        if (order.getStatus() != 1 && order.getStatus() != 6) {
            // 说明订单已经成功了
            try {
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return;
        }
        // 代码走到这里 说明订单失败了 我需要去找第三方支付做确认
        // TODO 去支付宝确认是否支付成功
        // 失败了
        try {
            handleOrderFail(order);
            try {
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            log.error("回滚失败，订单号为{}", orderNum);
        }

    }

    /**
     * 修改订单状态
     * 回滚mysql
     * 回滚es
     *
     * @param order
     */
    private void handleOrderFail(Order order) {
        order.setUpdateTime(new Date());
        order.setCancelTime(new Date());
        order.setCloseType(1);
        order.setStatus(6);
        boolean flag = orderService.updateById(order);
        if (flag) {
            // 回滚数据的操作  我们要把扣减的库存加回来
            List<OrderItem> orderItemList = orderItemService.list(new LambdaQueryWrapper<OrderItem>()
                    .eq(OrderItem::getOrderNumber, order.getOrderNumber())
            );
            if (CollectionUtils.isEmpty(orderItemList)) {
                log.error("此订单号{}对应的商品数为空", order.getOrderNumber());
                return;
            }
            StockChange stockChange = new StockChange();
            List<EsChange> esChanges = new ArrayList<>();
            List<SkuChange> skuChanges = new ArrayList<>();
            // 组装数据
            orderItemList.forEach(orderItem -> {
                Long skuId = orderItem.getSkuId();
                Long prodId = orderItem.getProdId();
                Integer count = orderItem.getProdCount();
                skuChanges.add(new SkuChange(skuId, count));
                List<EsChange> esChangeList = esChanges.stream()
                        .filter(esChange -> esChange.getProdId().equals(prodId))
                        .collect(Collectors.toList());
                if (CollectionUtils.isEmpty(esChangeList)) {
                    esChanges.add(new EsChange(prodId, count));
                } else {
                    EsChange esChange = esChangeList.get(0);
                    esChange.setCount(esChange.getCount() + count);
                }
            });

            stockChange.setSkuChanges(skuChanges);
            stockChange.setEsChanges(esChanges);
            // 发起远程调用
            orderProductFeign.changeStock(stockChange);
            // 通知es
            rabbitTemplate.convertAndSend(QueueConstant.PROD_CHANGE_EX, QueueConstant.PROD_CHANGE_KEY, JSON.toJSONString(esChanges));
        }
    }

}
